/**
 * Copyright (c) 2023 murenchao
 * taomu is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.toolkit.oltu.service

import java.net.URI
import javax.ws.rs.core.Response
import javax.ws.rs.core.UriBuilder
import org.apache.oltu.oauth2.^as.issuer.MD5Generator
import org.apache.oltu.oauth2.^as.issuer.OAuthIssuerImpl
import org.apache.oltu.oauth2.common.exception.OAuthProblemException
import org.apache.oltu.oauth2.common.exception.OAuthSystemException
import org.apache.oltu.oauth2.common.message.types.GrantType
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.ToString
import org.slf4j.LoggerFactory

class OAuth2ServerService {
	val static LOG = LoggerFactory.getLogger(OAuth2ServerService)

	interface IAuthorization {
		def boolean validateClient(String authCode, String clientId, String clientSecret);

		def boolean validateRefreshToken(String authCode, String refreshToken)

		def TokenEntity generateToken(String authCode, String accessToken, String refreshToken);

		def boolean authorizationCode(String authCode, String clientId, String clientSecret);

		def String redirectUri(String clientId, String clientSecret)
	}

	def static Response authorize(String responseType, String clientId, String clientSecret, IAuthorization auth) {
		var redirectUri = auth.redirectUri(clientId, clientSecret);
		try {
			// 生成授权码
			var String authorizationCode = new OAuthIssuerImpl(new MD5Generator()).authorizationCode();
			if ("code".equals(responseType) && auth.authorizationCode(authorizationCode, clientId, clientSecret)) {
				// 使用 UriBuilder 添加查询参数
				var URI location = UriBuilder.fromUri(redirectUri).queryParam("code", authorizationCode).build();
				return Response.seeOther(location).build();
			}
			return Response.status(Response.Status.BAD_REQUEST).entity("不支持的响应类型").build();

		} catch (OAuthProblemException e) {
			LOG.error("OAuthProblemException:{}", e.description);
			e.printStackTrace
			if (redirectUri !== null) {
				var URI location = UriBuilder.fromUri(redirectUri).queryParam("error", e.getError()).build();
				return Response.seeOther(location).build();
			}
			return Response.status(Response.Status.BAD_REQUEST).entity("缺少客户端回调地址").build();
		} catch (OAuthSystemException e) {
			LOG.error("OAuthSystemException:{}", e);
			return Response.serverError().entity("内部服务器错误").build();
		}
	}

	@Accessors
	@ToString
	static class TokenEntity {
		String accessToken;
		int expiresIn;
		String refreshToken;

		new(String accessToken, int expiresIn, String refreshToken) {
			this.accessToken = accessToken;
			this.expiresIn = expiresIn;
			this.refreshToken = refreshToken;
		}
	}

	def static Response token(String authCode, String grantType, String clientId, String clientSecret,
		String refreshToken, IAuthorization auth) {
		try {
			// 检查客户端ID和密钥
			if (!auth.validateClient(authCode, clientId, clientSecret)) {
				return Response.status(Response.Status.UNAUTHORIZED).entity("client_id或client_secret无效").build();
			}
			// 处理刷新令牌模式
			if (GrantType.REFRESH_TOKEN.name.equalsIgnoreCase(grantType)) {
				LOG.info("刷新令")
				if (!auth.validateRefreshToken(authCode, refreshToken)) {
					return Response.status(Response.Status.BAD_REQUEST).entity("刷新令牌无效或已过期").build();
				}
				// 生成新的访问令牌和刷新令牌
				var oi = new OAuthIssuerImpl(new MD5Generator());
				return Response.ok(auth.generateToken(authCode, oi.accessToken, oi.refreshToken)).build();
			}

			// 处理授权码模式
			if (GrantType.AUTHORIZATION_CODE.name.equalsIgnoreCase(grantType)) {
				LOG.info("授权码")
				var oi = new OAuthIssuerImpl(new MD5Generator())
				// 返回JSON格式的访问令牌
				return Response.ok(auth.generateToken(authCode, oi.accessToken, oi.refreshToken)).build();
			}
			return Response.status(Response.Status.BAD_REQUEST).entity("不支持的授权类型").build();
		} catch (OAuthSystemException e) {
			LOG.error("OAuthSystemException:", e);
			return Response.serverError().entity("内部服务器错误").build();
		}
	}
}
